package bloodfang;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Procs {
	
	public static String[] trinket_prefixes = new String[]{"lfr_","flex_","","war_","heroic_","heroic_war_"};
	private HashMap<String,ProcBehavior> behavior = new HashMap<String,ProcBehavior>();
	private List<ProcData> procData = new ArrayList<ProcData>();
	
	public ProcData get(String name){
		for(ProcData proc : getProcData()){
			if(proc.name.equals(name))
				return proc;
		}
		System.err.println("Error: proc " + name + " does not exists");
		return null;
	}
	
	public ProcBehavior getBehavior(String name){
		if(behavior.containsKey(name))
			return behavior.get(name);
		else{
			System.err.println("Error: proc behavior " + name + " does not exists");
			return null;
		}
	}
	
	public Procs(){
		// wod
		ProcBehavior motshb = new ProcBehavior();
		motshb.type = ProcType.DIRECT_DMG;
		motshb.rppm = 2;
		motshb.scaling_with_haste = true;
		motshb.scaling = false;
		behavior.put("mark_of_the_shattered_hand", motshb);
		
		ProcBehavior motfb = new ProcBehavior();
		motfb.duration = 6;
		motfb.rppm = 2.53;
		motfb.scaling = false;
		motfb.stacks = 2;
		motfb.stats.setStat(Stat.mul, 500);
		behavior.put("mark_of_the_frostwolf", motfb);
		
		// mop
		ProcBehavior totg_b = new ProcBehavior();
		totg_b.type = ProcType.DIRECT_DMG;
		totg_b.icd = 15.;
		totg_b.proc_chance = 0.2;
		totg_b.scaling = false;
		behavior.put("touch_of_the_grave", totg_b);
		
		ProcBehavior dsb = new ProcBehavior();
		dsb.duration = 12;
		dsb.rppm = 2.53;
		dsb.scaling = false;
		dsb.stats.setStat(Stat.agi, 83);
		behavior.put("dancing_steel", dsb);
		
		ProcBehavior fox_b = new ProcBehavior();
		fox_b.type = ProcType.DIRECT_DMG;
		fox_b.rppm = 1.62;
		fox_b.scaling_with_haste = true;
		fox_b.scaling = false;
		behavior.put("fury_of_xuen", fox_b);
		
		ProcBehavior cpdb = new ProcBehavior();
		cpdb.type = ProcType.DIRECT_DMG;
		cpdb.rppm = 19.27;
		cpdb.stacks = 5;
		cpdb.scaling_with_haste = true;
		cpdb.scaling = false;
		behavior.put("capacitive_primal_diamond", cpdb);
		
		ProcBehavior bad_juju = new ProcBehavior();
		bad_juju.duration = 10;
		bad_juju.icd = 10;
		bad_juju.rppm = 1.1;
		bad_juju.stats.setStat(Stat.agi, 2.4749999046);
		behavior.put("bad_juju", bad_juju);
		
		ProcBehavior ren = new ProcBehavior();
		ren.duration = 10;
		ren.icd = 10;
		ren.rppm = 1.21;
		ren.stats.setStat(Stat.agi, avg_ramping_up_value(0.4499999881,10));
		behavior.put("renatakis_soul_charm", ren);
		
		ProcBehavior tobb = new ProcBehavior();
		tobb.duration = 10;
		tobb.stacks = 5;
		tobb.rppm = 3.5;
		tobb.stats.setStat(Stat.hst, 0.5189999938);
		behavior.put("talisman_of_bloodlust", tobb);
		
		ProcBehavior shadopanassb = new ProcBehavior();
		shadopanassb.duration = 20;
		shadopanassb.icd = 115;
		shadopanassb.proc_chance = 0.15;
		shadopanassb.stats.setStat(Stat.agi, 2.9700000286);
		behavior.put("shado_pan_assault", shadopanassb);
		
		ProcBehavior assurance_of_consequenceb = new ProcBehavior();
		assurance_of_consequenceb.duration = 20;
		assurance_of_consequenceb.proc_chance = 0.15;
		assurance_of_consequenceb.icd = 115;
		assurance_of_consequenceb.stats.setStat(Stat.agi, 2.9730000496);
		behavior.put("assurance_of_consequence", assurance_of_consequenceb);
		
		ProcBehavior multistrike_b = new ProcBehavior();
		multistrike_b.type = ProcType.SPECIAL;
		multistrike_b.proc_chance = 0.0353999995 / 10;
		multistrike_b.proc_chance_scaling = true;
		behavior.put("multistrike", multistrike_b);
		
		// 2.9730000496
		ProcBehavior haromms_talisman_b = new ProcBehavior();
		haromms_talisman_b.duration = 10;
		haromms_talisman_b.icd = 10;
		haromms_talisman_b.rppm = 0.92;
		haromms_talisman_b.stats.setStat(Stat.agi, 2.9730000496);
		behavior.put("haromms_talisman", haromms_talisman_b);
		
		ProcBehavior cleave_b = new ProcBehavior();
		cleave_b.type = ProcType.SPECIAL;
		cleave_b.proc_chance = 0.0785999969 / 100;
		cleave_b.proc_chance_scaling = true;
		behavior.put("cleave", cleave_b);
		
		ProcBehavior sigil_of_rampage_b = new ProcBehavior();
		sigil_of_rampage_b.duration = 15;
		sigil_of_rampage_b.proc_chance = 0.15;
		sigil_of_rampage_b.icd = 85;
		sigil_of_rampage_b.stats.setStat(Stat.agi, 2.9730000496);
		behavior.put("sigil_of_rampage", sigil_of_rampage_b);
		
		ProcBehavior ticking_ebon_detonator_b = new ProcBehavior();
		ticking_ebon_detonator_b.duration = 10; // every 0.5 sec it is reduced
		ticking_ebon_detonator_b.icd = 10;
		ticking_ebon_detonator_b.rppm = 1.01;
		ticking_ebon_detonator_b.stats.setStat(Stat.agi, avg_ramping_up_value(0.2703000009, 20));
		behavior.put("ticking_ebon_detonator", ticking_ebon_detonator_b);
		
		ProcBehavior discipline_of_xuen_b = new ProcBehavior();
		discipline_of_xuen_b.duration = 20;
		discipline_of_xuen_b.proc_chance = 0.15;
		discipline_of_xuen_b.icd = 115;
		discipline_of_xuen_b.stats.setStat(Stat.mst, 2.9730000496);
		behavior.put("discipline_of_xuen", discipline_of_xuen_b);
		
		ProcBehavior thoks_tail_tip_b = new ProcBehavior();
		thoks_tail_tip_b.duration = 20;
		thoks_tail_tip_b.proc_chance = 0.15;
		thoks_tail_tip_b.icd = 115;
		thoks_tail_tip_b.stats.setStat(Stat.str, 2.9730000496);
		behavior.put("thoks_tail_tip", thoks_tail_tip_b);
		
		
		/////////////////////////////////////////////////////////
		
		// wop
		ProcData mhmotsh = new ProcData();
		mhmotsh.name = "mh_mark_of_the_shattered_hand";
		mhmotsh.behavior = behavior.get("mark_of_the_shattered_hand");
		getProcData().add(mhmotsh);
		
		ProcData ohmotsh = new ProcData();
		ohmotsh.name = "oh_mark_of_the_shattered_hand";
		ohmotsh.behavior = behavior.get("mark_of_the_shattered_hand");
		getProcData().add(ohmotsh);
		
		ProcData mhmotf = new ProcData();
		mhmotf.name = "mh_mark_of_the_frostwolf";
		mhmotf.behavior = behavior.get("mark_of_the_frostwolf");
		getProcData().add(mhmotf);
		
		ProcData ohmotf = new ProcData();
		ohmotf.name = "oh_mark_of_the_frostwolf";
		ohmotf.behavior = behavior.get("mark_of_the_frostwolf");
		getProcData().add(ohmotf);
		
		// mop
		ProcData totg = new ProcData();
		totg.name = "touch_of_the_grave";
		totg.behavior = behavior.get("touch_of_the_grave");
		getProcData().add(totg);
		
		ProcData mhds = new ProcData();
		mhds.name = "mh_dancing_steel";
		mhds.behavior = behavior.get("dancing_steel");
		getProcData().add(mhds);
		
		ProcData ohds = new ProcData();
		ohds.name = "oh_dancing_steel";
		ohds.behavior = behavior.get("dancing_steel");
		getProcData().add(ohds);
		
		ProcData fox = new ProcData();
		fox.name = "fury_of_xuen";
		fox.behavior = behavior.get("fury_of_xuen");
		getProcData().add(fox);
		
		ProcData cpd = new ProcData();
		cpd.name = "capacitive_primal_diamond";
		cpd.behavior = behavior.get("capacitive_primal_diamond");
		getProcData().add(cpd);
		
		ProcData rsc = new ProcData();
		rsc.name = "renatakis_soul_charm";
		rsc.base_lvl = 522;
		rsc.behavior = behavior.get("renatakis_soul_charm");
		getProcData().add(rsc);
		
		ProcData rsclfr = new ProcData();
		rsclfr.name = "lfr_renatakis_soul_charm";
		rsclfr.base_lvl = 502;
		rsclfr.behavior = behavior.get("renatakis_soul_charm");
		getProcData().add(rsclfr);
		
		ProcData rsch = new ProcData();
		rsch.name = "heroic_renatakis_soul_charm";
		rsch.base_lvl = 535;
		rsch.behavior = behavior.get("renatakis_soul_charm");
		getProcData().add(rsch);
		
		ProcData rscht = new ProcData();
		rscht.name = "heroic_thunder_renatakis_soul_charm";
		rscht.base_lvl = 541;
		rscht.behavior = behavior.get("renatakis_soul_charm");
		getProcData().add(rscht);
		
		ProcData tob = new ProcData();
		tob.name = "talisman_of_bloodlust";
		tob.base_lvl = 522;
		tob.behavior = behavior.get("talisman_of_bloodlust");
		getProcData().add(tob);
		
		ProcData toblfr = new ProcData();
		toblfr.name = "lfr_talisman_of_bloodlust";
		toblfr.base_lvl = 502;
		toblfr.behavior = behavior.get("talisman_of_bloodlust");
		getProcData().add(toblfr);
		
		ProcData tobh = new ProcData();
		tobh.name = "heroic_talisman_of_bloodlust";
		tobh.base_lvl = 535;
		tobh.behavior = behavior.get("talisman_of_bloodlust");
		getProcData().add(tobh);
		
		ProcData tobht = new ProcData();
		tobht.name = "heroic_thunder_talisman_of_bloodlust";
		tobht.base_lvl = 541;
		tobht.behavior = behavior.get("talisman_of_bloodlust");
		getProcData().add(tobht);
		
		ProcData bj = new ProcData();
		bj.name = "bad_juju";
		bj.base_lvl = 522;
		bj.behavior = behavior.get("bad_juju");
		getProcData().add(bj);
		
		ProcData bjlfr = new ProcData();
		bjlfr.name = "lfr_bad_juju";
		bjlfr.base_lvl = 502;
		bjlfr.behavior = behavior.get("bad_juju");
		getProcData().add(bjlfr);
		
		ProcData bjh = new ProcData();
		bjh.name = "heroic_bad_juju";
		bjh.base_lvl = 535;
		bjh.behavior = behavior.get("bad_juju");
		getProcData().add(bjh);
		
		ProcData bjht = new ProcData();
		bjht.name = "heroic_thunder_bad_juju";
		bjht.base_lvl = 541;
		bjht.behavior = behavior.get("bad_juju");
		getProcData().add(bjht);
		
		ProcData spa = new ProcData();
		spa.name = "shado_pan_assault";
		spa.base_lvl = 522;
		spa.behavior = behavior.get("shado_pan_assault");
		getProcData().add(spa);
		
		ProcData agidpstrinket1 = new ProcData();
		agidpstrinket1.name = "assurance_of_consequence";
		agidpstrinket1.base_lvl = 553;
		agidpstrinket1.behavior = behavior.get("assurance_of_consequence");
		getProcData().add(agidpstrinket1);
		
		ProcData aoclfr = new ProcData();
		aoclfr.name = "lfr_assurance_of_consequence";
		aoclfr.base_lvl = 528;
		aoclfr.behavior = behavior.get("assurance_of_consequence");
		getProcData().add(aoclfr);
		
		ProcData aocflex = new ProcData();
		aocflex.name = "flex_assurance_of_consequence";
		aocflex.base_lvl = 540;
		aocflex.behavior = behavior.get("assurance_of_consequence");
		getProcData().add(aocflex);
		
		ProcData aocw = new ProcData();
		aocw.name = "war_assurance_of_consequence";
		aocw.base_lvl = 559;
		aocw.behavior = behavior.get("assurance_of_consequence");
		getProcData().add(aocw);
		
		ProcData aoch = new ProcData();
		aoch.name = "heroic_assurance_of_consequence";
		aoch.base_lvl = 566;
		aoch.behavior = behavior.get("assurance_of_consequence");
		getProcData().add(aoch);
		
		ProcData aochw = new ProcData();
		aochw.name = "heroic_war_assurance_of_consequence";
		aochw.base_lvl = 572;
		aochw.behavior = behavior.get("assurance_of_consequence");
		getProcData().add(aochw);
		
		ProcData agidpstrinket2 = new ProcData();
		agidpstrinket2.name = "haromms_talisman";
		agidpstrinket2.base_lvl = 553;
		agidpstrinket2.behavior = behavior.get("haromms_talisman");
		getProcData().add(agidpstrinket2);
		
		ProcData htlfr = new ProcData();
		htlfr.name = "lfr_haromms_talisman";
		htlfr.base_lvl = 528;
		htlfr.behavior = behavior.get("haromms_talisman");
		getProcData().add(htlfr);
		
		ProcData htflex = new ProcData();
		htflex.name = "flex_haromms_talisman";
		htflex.base_lvl = 540;
		htflex.behavior = behavior.get("haromms_talisman");
		getProcData().add(htflex);
		
		ProcData htw = new ProcData();
		htw.name = "war_haromms_talisman";
		htw.base_lvl = 559;
		htw.behavior = behavior.get("haromms_talisman");
		getProcData().add(htw);
		
		ProcData hth = new ProcData();
		hth.name = "heroic_haromms_talisman";
		hth.base_lvl = 566;
		hth.behavior = behavior.get("haromms_talisman");
		getProcData().add(hth);
		
		ProcData hthw = new ProcData();
		hthw.name = "heroic_war_haromms_talisman";
		hthw.base_lvl = 572;
		hthw.behavior = behavior.get("haromms_talisman");
		getProcData().add(hthw);
		
//		ProcData multistrike = new ProcData();
//		multistrike.name = "multistrike";
//		multistrike.base_lvl = 553;
//		multistrike.behavior = behavior.get("multistrike");
//		getProcData().add(multistrike);
		
		ProcData agidpstrinket3 = new ProcData();
		agidpstrinket3.name = "sigil_of_rampage";
		agidpstrinket3.base_lvl = 553;
		agidpstrinket3.behavior = behavior.get("sigil_of_rampage");
		getProcData().add(agidpstrinket3);
		
		ProcData sorlfr = new ProcData();
		sorlfr.name = "lfr_sigil_of_rampage";
		sorlfr.base_lvl = 528;
		sorlfr.behavior = behavior.get("sigil_of_rampage");
		getProcData().add(sorlfr);
		
		ProcData sorflex = new ProcData();
		sorflex.name = "flex_sigil_of_rampage";
		sorflex.base_lvl = 540;
		sorflex.behavior = behavior.get("sigil_of_rampage");
		getProcData().add(sorflex);
		
		ProcData sorw = new ProcData();
		sorw.name = "war_sigil_of_rampage";
		sorw.base_lvl = 559;
		sorw.behavior = behavior.get("sigil_of_rampage");
		getProcData().add(sorw);
		
		ProcData sorh = new ProcData();
		sorh.name = "heroic_sigil_of_rampage";
		sorh.base_lvl = 566;
		sorh.behavior = behavior.get("sigil_of_rampage");
		getProcData().add(sorh);
		
		ProcData sorhw = new ProcData();
		sorhw.name = "heroic_war_sigil_of_rampage";
		sorhw.base_lvl = 572;
		sorhw.behavior = behavior.get("sigil_of_rampage");
		getProcData().add(sorhw);
		
//		ProcData cleave = new ProcData();
//		cleave.name = "cleave";
//		cleave.base_lvl = 553;
//		cleave.behavior = behavior.get("cleave");
//		getProcData().add(cleave);
		
		ProcData agidpstrinket4 = new ProcData();
		agidpstrinket4.name = "ticking_ebon_detonator";
		agidpstrinket4.base_lvl = 553;
		agidpstrinket4.behavior = behavior.get("ticking_ebon_detonator");
		getProcData().add(agidpstrinket4);
		
		ProcData tedlfr = new ProcData();
		tedlfr.name = "lfr_ticking_ebon_detonator";
		tedlfr.base_lvl = 528;
		tedlfr.behavior = behavior.get("ticking_ebon_detonator");
		getProcData().add(tedlfr);
		
		ProcData tedflex = new ProcData();
		tedflex.name = "flex_ticking_ebon_detonator";
		tedflex.base_lvl = 540;
		tedflex.behavior = behavior.get("ticking_ebon_detonator");
		getProcData().add(tedflex);
		
		ProcData tedw = new ProcData();
		tedw.name = "war_ticking_ebon_detonator";
		tedw.base_lvl = 559;
		tedw.behavior = behavior.get("ticking_ebon_detonator");
		getProcData().add(tedw);
		
		ProcData tedh = new ProcData();
		tedh.name = "heroic_ticking_ebon_detonator";
		tedh.base_lvl = 566;
		tedh.behavior = behavior.get("ticking_ebon_detonator");
		getProcData().add(tedh);
		
		ProcData tedhw = new ProcData();
		tedhw.name = "heroic_war_ticking_ebon_detonator";
		tedhw.base_lvl = 572;
		tedhw.behavior = behavior.get("ticking_ebon_detonator");
		getProcData().add(tedhw);
		
		ProcData dox = new ProcData();
		dox.name = "discipline_of_xuen";
		dox.base_lvl = 496;
		dox.behavior = behavior.get("discipline_of_xuen");
		getProcData().add(dox);
		
		ProcData dox_timeless = new ProcData();
		dox_timeless.name = "timeless_discipline_of_xuen";
		dox_timeless.base_lvl = 535;
		dox_timeless.behavior = behavior.get("discipline_of_xuen");
		getProcData().add(dox_timeless);
		
		ProcData ttt = new ProcData();
		ttt.name = "thoks_tail_tip";
		ttt.base_lvl = 553;
		ttt.behavior = behavior.get("thoks_tail_tip");
		getProcData().add(ttt);
	}
	
	private double avg_ramping_up_value(double base_value, int max_stacks){
		double sum = 0.0;
		for(int i = 1; i <= max_stacks; i++){
			sum += base_value * i;
		}
		return sum / max_stacks;
	}

	public double getCapacitivePrimalDiamondRPPM(Spec spec) {
		double rppm = 19.27;
		if(spec == Spec.ASSASSINATION)
			rppm *= 1.789;
		else if(spec == Spec.COMBAT)
			rppm *= 1.136;
		else if(spec == Spec.SUBTLETY)
			rppm *= 1.114;
		return rppm;
	}

	public List<ProcData> getProcData() {
		return procData;
	}

	public void setProcData(List<ProcData> procData) {
		this.procData = procData;
	}
}
